package com.px.patient.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.patient.domain.CollectCostPatients;
import com.px.patient.domain.CollectCostPatientsDetails;
import com.px.patient.domain.MedicalRecordDetails;
import com.px.patient.domain.Patient;
import com.px.patient.domain.PatientAppointment;
import com.px.patient.enums.PatientAppointmentStatusEnum;
import com.px.patient.mapper.CollectCostPatientsMapper;
import com.px.patient.service.ICollectCostPatientsDetailsService;
import com.px.patient.service.ICollectCostPatientsService;
import com.px.patient.service.IDiagnosisTypeCostProjectService;
import com.px.patient.service.IPatientAppointmentService;
import com.px.patient.service.IPatientService;
import com.px.patient.vo.DiagnosisTypeCostProjectInfoVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * CollectCostPatientsServiceImpl
 *
 * @author 品讯科技
 * @date: 2024/05/17 15:39
 */
@Service
public class CollectCostPatientsServiceImpl extends ServiceImpl<CollectCostPatientsMapper, CollectCostPatients> implements ICollectCostPatientsService {

    @Resource
    private IDiagnosisTypeCostProjectService diagnosisTypeCostProjectService;
    @Resource
    private ICollectCostPatientsDetailsService collectCostPatientsDetailsService;
    @Resource
    private IPatientService patientService;
    @Resource
    private IPatientAppointmentService patientAppointmentService;


    /**
     * 保存收费信息到病历
     *
     * @param recordDetailsList 参数
     * @param patientId         患者id
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public BigDecimal saveCollectCostPatientsToMedicalRecord(List<MedicalRecordDetails> recordDetailsList, String patientId) {
        // 给病例详情分组，每颗牙是一个集合
        Map<String, List<MedicalRecordDetails>> collect =
                recordDetailsList.stream().collect(Collectors.groupingBy(MedicalRecordDetails::getToothPosition));

        // 先保存收费初始信息
        CollectCostPatients collectCostPatients = saveCostInfo(recordDetailsList.get(0).getMedicalRecordId(), patientId);

        // 保存患者收费详情
        BigDecimal receivableCost = saveCollectCostPatientsDetails(collect, collectCostPatients.getId());

        // 更新应收费用
        CollectCostPatients costPatients = new CollectCostPatients();
        costPatients.setReceivableCost(receivableCost);
        costPatients.setAmountCost(receivableCost);
        costPatients.setId(collectCostPatients.getId());
        this.updateById(costPatients);
        return receivableCost;
    }

    /**
     * 收费
     *
     * @param entry 参数
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void collectCost(CollectCostPatients entry) {
        CollectCostPatients costPatients = this.getById(entry.getId());
        if (Objects.isNull(costPatients)) {
            throw new RuntimeException("收费信息不存在");
        }

        CollectCostPatients collectCostPatients = new CollectCostPatients();
        collectCostPatients.setId(entry.getId());
        collectCostPatients.setNetReceiptsCost(entry.getNetReceiptsCost());
        collectCostPatients.setCostStatus(2);

        this.updateById(collectCostPatients);
        patientAppointmentService.update(Wrappers.<PatientAppointment>lambdaUpdate()
                .set(PatientAppointment::getAppointmentStatus, PatientAppointmentStatusEnum.CLOSED.getCode())
                .eq(PatientAppointment::getMedicalRecordId, costPatients.getMedicalRecordId()));
    }

    /**
     * 保存患者收费详情
     *
     * @param collect               病例详情分组
     * @param collectCostPatientsId 收费信息ID
     * @return BigDecimal
     */
    private BigDecimal saveCollectCostPatientsDetails(Map<String, List<MedicalRecordDetails>> collect, String collectCostPatientsId) {
        BigDecimal receivableCost = new BigDecimal(0);
        List<CollectCostPatientsDetails> collectCostPatientsDetailsList = new ArrayList<>();
        for (String toothPosition : collect.keySet()) {
            MedicalRecordDetails medicalRecordDetails = collect.get(toothPosition).get(0);

            DiagnosisTypeCostProjectInfoVO entry = new DiagnosisTypeCostProjectInfoVO();
            entry.setDiagnosisTypeId(medicalRecordDetails.getDiagnosisTypeId());
            List<DiagnosisTypeCostProjectInfoVO> list = diagnosisTypeCostProjectService.findList(entry);
            if (CollectionUtils.isEmpty(list)) {
                continue;
            }
            // 根据诊断分类id查询收费项目，保存到收费详情中
            for (DiagnosisTypeCostProjectInfoVO vo : list) {
                CollectCostPatientsDetails details = new CollectCostPatientsDetails();
                details.setCollectCostPatientsId(collectCostPatientsId);
                details.setProjectCode(vo.getProjectCode());
                details.setProjectName(vo.getProjectName());
                details.setUnitPrice(vo.getUnitPrice());
                details.setPreferentialPrice(vo.getUnitPrice());
                details.setUnit(vo.getUnit());
                details.setToothPosition(medicalRecordDetails.getToothPosition());
                details.setTotal(vo.getTotal());
                details.setId(null);
                collectCostPatientsDetailsList.add(details);
                // 计算应收费用 单价*数量
                BigDecimal total = vo.getUnitPrice().multiply(new BigDecimal(vo.getTotal()));
                receivableCost = receivableCost.add(total);
            }
        }
        // 保存患者收费详情
        collectCostPatientsDetailsService.saveDetailsByCollectCostPatientsId(collectCostPatientsId, collectCostPatientsDetailsList);
        return receivableCost;
    }

    /**
     * 保存收费信息
     *
     * @param medicalRecordId 病例id
     * @return CollectCostPatients
     */
    private CollectCostPatients saveCostInfo(String medicalRecordId, String patientId) {
        Patient patient = patientService.getById(patientId);
        if (Objects.isNull(patient)) {
            throw new RuntimeException("患者不存在");
        }
        CollectCostPatients collectCostPatients = new CollectCostPatients();
        collectCostPatients.setPatientId(patientId);
        collectCostPatients.setPatientName(patient.getPatientName());
        collectCostPatients.setCostStatus(1);
        collectCostPatients.setMedicalRecordId(medicalRecordId);
        this.save(collectCostPatients);
        return collectCostPatients;
    }


}
